using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using WCamera;
using COC.Graphics;
using LuaInterface;
using LuaNetInterface;
using COC.Sound;

namespace COC
{
	/// <summary>
	/// This is the main type for your game
	/// </summary>
	public partial class CoCGame : Microsoft.Xna.Framework.Game
	{
		#region Singleton
		static CoCGame _SingletonInstance = null;
		public static CoCGame Singleton
		{
			get
			{
				if (_SingletonInstance == null)
				{
					_SingletonInstance = new CoCGame();
				}
				return _SingletonInstance;
			}
		}
		#endregion

		#region Core Obj
		GraphicsDeviceManager m_graphics;
		SpriteBatch m_spriteBatch;
		InternalConsole m_Console;
		BloomComponent m_bloom;

		public InternalConsole Console
		{
			get { return m_Console; }
		}

		SpriteFont m_Font;
		Camera m_camera;
		LuaVirtualMachine m_LuaVM;
		public Camera GameCamera { get { return m_camera; } }

		#endregion

		#region Graphics Components
		//SkydomeComponent m_SkyDome;
		GameWorld m_GameWorld;
		public GameWorld CurrentGameWorld
		{
			get { return m_GameWorld; }
		}

		#endregion

		#region .ctor
		CoCGame()
		{
			m_graphics = new GraphicsDeviceManager(this);
			//m_graphics.PreferMultiSampling = true;

			Content.RootDirectory = "Content";
			this.Disposed += new EventHandler(WiscapeGame_Disposed);

			m_GameWorld = new GameWorld(this);
			m_LuaVM = new LuaVirtualMachine();

			m_Console = new InternalConsole(this);
			m_Console.OnCommandLine += OnCommandLine;
			Components.Add(m_GameWorld);

			//m_bloom = new BloomComponent(this);
			//Components.Add(m_bloom);
		}
		#endregion

		/// <summary>
		/// Allows the game to perform any initialization it needs to before starting to run.
		/// This is where it can query for any required services and load any non-graphic
		/// related content.  Calling base.Initialize will enumerate through any components
		/// and initialize them as well.
		/// </summary>
		protected override void Initialize()
		{
			// TODO: Add your initialization logic here
			m_camera = new Camera();
			m_camera.ViewPort = GraphicsDevice.Viewport;

			//m_SkyDome = new SkydomeComponent();
			//m_GameWorld = new GameWorld(this);
			//this.Window.AllowUserResizing = true;

			base.Initialize();

			m_LuaVM.RegisterLuaFunctions(m_GameWorld.m_SkyDome);
			m_LuaVM.RegisterLuaFunctions(m_GameWorld);
		}

		/// <summary>
		/// LoadContent will be called once per game and is the place to load
		/// all of your content.
		/// </summary>
		protected override void LoadContent()
		{
			// Create a new SpriteBatch, which can be used to draw textures.
			m_spriteBatch = new SpriteBatch(GraphicsDevice);
			m_Font = Content.Load<SpriteFont>(@"Fonts\Arial");
			m_Console.Initialize(m_Font);
			SoundManager.InitializeSounds(Content);

			// TODO: use this.Content to load your game content here
			//m_GameWorld.Initialize();
		}

		/// <summary>
		/// UnloadContent will be called once per game and is the place to unload
		/// all content.
		/// </summary>
		protected override void UnloadContent()
		{
			// TODO: Unload any non ContentManager content here
			m_GameWorld.Dispose();
			m_Console.Dispose();
		}

		/// <summary>
		/// Allows the game to run logic such as updating the world,
		/// checking for collisions, gathering input, and playing audio.
		/// </summary>
		/// <param name="gameTime">Provides a snapshot of timing values.</param>
		protected override void Update(GameTime gameTime)
		{
			// TODO: Add your update logic here
			HandleInput(gameTime);

			base.Update(gameTime);
		}

		/// <summary>
		/// This is called when the game should draw itself.
		/// </summary>
		/// <param name="gameTime">Provides a snapshot of timing values.</param>
		protected override void Draw(GameTime gameTime)
		{
			GraphicsDevice.Clear(Color.CornflowerBlue);

			// TODO: Add your drawing code here
			base.Draw(gameTime);
			m_Console.Draw(m_spriteBatch);
		}

		void WiscapeGame_Disposed(object sender, EventArgs e)
		{
			_SingletonInstance = null;
		}

		void OnCommandLine(object sender, CommandLineEventArgs e)
		{
			try
			{
				if (m_LuaVM != null)
				{
					if (m_LuaVM.IsRunning)
					{
						object[] ret = m_LuaVM.Lua.DoString(e.CommandLine);
						if(ret != null && ret.Length > 0)
						{
							foreach (object obj in ret)
							{
								m_Console.WriteLine(obj.ToString());
							}
						}
					}
					else
						m_Console.WriteLine("ERROR: Lua Virtual Machine is no longer running.");
				}
				else
					m_Console.WriteLine("ERROR: Lua Virtual Machine has not been set.");
			}
			catch (LuaException el)
			{
				m_Console.WriteLine("Lua Error: " + el.Message);
			}
		}
	}
}